#pragma once

#include "Socket.h"
#include "Mutex.h"
#include "BackgroundWorker.h"

namespace Core
{
	class BufferedSocketListener
	{
	public:
		virtual ~BufferedSocketListener() {};
		virtual void MessageReceived() {};
		virtual void MessageSent() {};
		virtual void ConnectionClosed() {};
	};

	class BufferedSocket : public Socket
	{
	protected:
		BufferedSocketListener* m_BufferedSocketListener;
		BackgroundWorker<BufferedSocket> m_Receiver;
		BackgroundWorker<BufferedSocket> m_Sender;
		Mutex m_ReceiverMutex;
		Mutex m_SenderMutex;
		std::queue<RawData> m_ReceiverBuffer;
		std::queue<InternetAddress> m_ReceiverAddressBuffer;
		std::queue<RawData> m_SenderBuffer;
		std::queue<InternetAddress> m_SenderAddressBuffer;
		virtual void Receiver();
		virtual void Sender();

	public:
		BufferedSocket(Socket p_Socket);
		virtual	~BufferedSocket();
		bool IsReceiverEmpty();
		bool IsSenderEmpty();
		void SetListener(BufferedSocketListener* p_BufferedSocketListener);
		virtual bool Receive(RawData& p_RawData, int p_TimeOutMilliSeconds = -1);
		virtual bool ReceiveFrom(RawData& p_RawData, InternetAddress& p_InternetAddress, int p_TimeOutMilliSeconds = -1);
		virtual bool Send(RawData& p_RawData, int p_TimeOutMilliSeconds = -1);
		virtual bool SendTo(RawData& p_RawData, InternetAddress& p_InternetAddress, int p_TimeOutMilliSeconds = -1);
		virtual void StartAll();
		virtual void StartReceiver();
		virtual void StartSender();
		virtual void StopAll();
	};
}
